/*
 * © 2024 huayunliufeng保留所有权利, 依据MIT许可证发布。
 * 请勿更改或删除版权声明或此文件头。
 * 此代码是免费软件, 您可以重新分发和/或修改它。
 * 开源是希望它有用, 但不对代码做任何保证。
 * 如有疑问请联系: huayunliufeng@163.com
 */

package io.github.huayunliufeng.dbinfo.dbinfo;

import io.github.huayunliufeng.common.utils.HylfDataUtil;
import io.github.huayunliufeng.common.utils.HylfFunUtil;
import io.github.huayunliufeng.dbinfo.model.PseudoColumnsInfo;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * <p>检索指定目录和模式中给定表中可用的伪列或隐藏列的描述。</p>
 * <p>伪列或隐藏列可能并不总是存储在表中，并且在ResultSet中不可见，除非在查询最外层的SELECT列表中指定它们。</p>
 * <p>伪列或隐藏列不一定能够被修改。如果没有伪列或隐藏列，则返回空ResultSet。</p>
 * <p>只返回与目录、模式、表和列名条件匹配的列描述。它们按TABLE_CAT、TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME排序。</p>
 *
 * @author zhongq
 * @datetime 2024/4/1 10:28
 */
public class ObtainPseudoColumnsInfo extends ObtainDbInfo {
    private static Map<Connection, ObtainPseudoColumnsInfo> obtainPseudoColumnsInfoMap = null;

    private Map<String, List<PseudoColumnsInfo>> pseudoColumnsInfoMap = null;

    protected ObtainPseudoColumnsInfo(Connection conn) {
        super(conn);
    }

    public static ObtainPseudoColumnsInfo build(Connection conn) {
        obtainPseudoColumnsInfoMap = HylfFunUtil.mapAddValue(obtainPseudoColumnsInfoMap, conn, () -> new ObtainPseudoColumnsInfo(conn));
        return obtainPseudoColumnsInfoMap.get(conn);
    }

    /**
     * <p>检索指定目录和模式中给定表中可用的伪列或隐藏列的描述。</p>
     * <p>伪列或隐藏列可能并不总是存储在表中，并且在ResultSet中不可见，除非在查询最外层的SELECT列表中指定它们。</p>
     * <p>伪列或隐藏列不一定能够被修改。如果没有伪列或隐藏列，则返回空ResultSet。</p>
     * <p>只返回与目录、模式、表和列名条件匹配的列描述。它们按TABLE_CAT、TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME排序。</p>
     *
     * @param catalog           目录名称;必须与存储在数据库中的目录名称匹配;“”检索那些没有目录的;null表示不应使用目录名称来缩小搜索范围
     * @param schemaPattern     模式名称模式;必须与存储在数据库中的模式名称匹配;""检索那些没有模式的;null表示不应该使用模式名称来缩小搜索范围
     * @param tableNamePattern  一个表名模式;必须匹配存储在数据库中的表名
     * @param columnNamePattern 列名模式;必须匹配存储在数据库中的列名
     * @return 每行是一个列描述
     */
    public List<PseudoColumnsInfo> getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) {
        String logFormat = "获取数据库表PseudoColumns信息失败。[catalog = {}, schemaPattern = {}, tableNamePattern = {}, columnNamePattern = {}]";
        return HylfFunUtil.methodVoidReturnExec(() -> {
            String key = String.join("-", catalog, schemaPattern, tableNamePattern);
            pseudoColumnsInfoMap = HylfFunUtil.mapAddValue(pseudoColumnsInfoMap, key, () -> {
                ResultSet resultSet = HylfFunUtil.methodVoidReturnExec(
                        () -> databaseMetaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern)
                        , logFormat, catalog, schemaPattern, tableNamePattern, columnNamePattern);
                List<PseudoColumnsInfo> pseudoColumnsInfoList = HylfDataUtil.autoSetValue(resultSet, PseudoColumnsInfo.class);
                HylfFunUtil.autoClose(resultSet);
                return pseudoColumnsInfoList;
            });
            return pseudoColumnsInfoMap.get(key);
        });
    }

    /**
     * <p>检索指定目录和模式中给定表中可用的伪列或隐藏列的描述。</p>
     * <p>伪列或隐藏列可能并不总是存储在表中，并且在ResultSet中不可见，除非在查询最外层的SELECT列表中指定它们。</p>
     * <p>伪列或隐藏列不一定能够被修改。如果没有伪列或隐藏列，则返回空ResultSet。</p>
     * <p>只返回与目录、模式、表和列名条件匹配的列描述。它们按TABLE_CAT、TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME排序。</p>
     *
     * @param tableNamePattern  一个表名模式;必须匹配存储在数据库中的表名
     * @param columnNamePattern 列名模式;必须匹配存储在数据库中的列名
     * @return 每行是一个列描述
     */
    public List<PseudoColumnsInfo> getPseudoColumns(String tableNamePattern, String columnNamePattern) {
        return getPseudoColumns(getCatalog(), getSchema(), tableNamePattern, columnNamePattern);
    }
}
